package org.linlinjava.litemall.wx.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.lang.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.common.annotations.VisibleForTesting;
import org.linlinjava.litemall.core.exception.BusinessRuntimeException;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.ResponseUtil.Response;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.wx.vo.*;
import org.linlinjava.litemall.wx.vo.category.CategoryListVO;
import org.linlinjava.litemall.wx.vo.packagegoods.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static org.linlinjava.litemall.core.exception.util.ServiceExceptionUtil.exception;
import static org.linlinjava.litemall.wx.errorcode.ErrorCodeConstants.LUMIERE_PACKAGE_IS_NULL;
import static org.linlinjava.litemall.wx.util.WxResponseCode.GOODS_UNKNOWN;

/**
 * 商品Service
 * @author lilu
 *
 */
@Service
public class WxGoodsService {

    @Autowired
    private LitemallGoodsService goodsService;
    @Autowired
    private LitemallGoodsSpecificationService specService;
    @Autowired
    private LitemallGoodsAccessoryService accessoryService;
    @Autowired
    private LitemallGoodsSpecificationMerchandiseService specMerchandiseService;
	@Autowired
	private LumiereGoodsFormulaCorrelationService lumiereGoodsFormulaCorrelationService;
	@Autowired
	private LitemallShopRegionService shopRegionService;
	@Autowired
	private LitemallRegionService litemallRegionService;
	@Autowired
	private LitemallGoodsPropertyService goodsPropertyService;
	@Autowired
	private LitemallGoodsAttributeService goodsAttributeService;
	@Autowired
	private LitemallGoodsRegionService litemallGoodsRegionService;
	@Autowired
	private LitemallTaxService litemallTaxService;
	@Autowired
	private LitemallCollectService collectService;
	@Autowired
	private LitemallMerchandiseService litemallMerchandiseService;
	@Autowired
	private LitemallCollectAccessoryService litemallCollectAccessoryService;
	@Autowired
	private LitemallCategoryService categoryService;
	@Autowired
	private LitemallGoodsRegionService goodsRegionService;

	@Autowired
	private LitemallCartService litemallCartService;

	@Autowired
	private LitemallShopService litemallShopService;

	@Autowired
	private LumierePackageService lumierePackageService;

	@Autowired
	private LumierePackageCategoryService lumierePackageCategoryService;

	@Autowired
	private LumierePackageCategoryGoodsService lumierePackageCategoryGoodsService;

	@Autowired
	private LitemallCartGoodsAccessoryService litemallCartGoodsAccessoryService;

	@Autowired
	private LitemallCartGoodsPropertyService litemallCartGoodsPropertyService;

	@Autowired
	private LumiereFormulaService lumiereFormulaService;

	@Autowired
	private LumiereFormulaTypeService lumiereFormulaTypeService;

	@Autowired
	private LumiereFormulaMaterialService lumiereFormulaMaterialService;

	@Autowired
	private LumiereFormulaSpecificationsService lumiereFormulaSpecificationsService;

	@Autowired
	private LumiereFormulaSpecificationsDataProportioningService lumiereFormulaSpecificationsDataProportioningService;


	 /**
     * 获取店铺的地区id
     * @param shopId
     */
    public Integer getShopCityRegionId(Integer shopId) {
    	List<LitemallShopRegion> litemallShopRegions = shopRegionService.queryByShopId(shopId);
    	if(!CollectionUtils.isEmpty(litemallShopRegions)) {
			for (LitemallShopRegion litemallShopRegion : litemallShopRegions) {
				LitemallRegion litemallRegion = litemallRegionService.findById(litemallShopRegion.getRegionId());
				if(Constants.REGION_TYPE_CITY == litemallRegion.getType()) {
					return litemallShopRegion.getRegionId();
				}
			}
		}
    	return null;
    }

    /**
     * 查询商品详情
     * @param shopId
	 * @param id 商品id
	 * @param userId
     * @return
     */
    public Response detail(Integer shopId, Integer id, Integer userId) {
		LitemallGoods goods = goodsService.findById(id);
		if (null == goods) {
			return ResponseUtil.fail(GOODS_UNKNOWN, "商品不存在");
		}

		GoodsDetailVO vo = new GoodsDetailVO();
		BeanUtils.copyProperties(goods, vo);

		//查询属性列表
		List<GoodsPropertyVO> propertyVos = new ArrayList<>();
		List<LitemallGoodsProperty> propList = goodsPropertyService.queryByGoodsId(id);
		if (!CollectionUtils.isEmpty(propList)) {
			for (LitemallGoodsProperty litemallGoodsProperty : propList) {
				GoodsPropertyVO propertyVo = new GoodsPropertyVO();
				propertyVo.setId(litemallGoodsProperty.getId());
				propertyVo.setName(litemallGoodsProperty.getName());

				List<GoodsPropertyVO.GoodsDetailPropertyVO> vos = new ArrayList();
				String[] values = litemallGoodsProperty.getValues();
				for (int i = 0; i < values.length; i++) {
					GoodsPropertyVO.GoodsDetailPropertyVO v = new GoodsPropertyVO.GoodsDetailPropertyVO();
					v.setName(values[i]);
					v.setIsSelected(values[i].equals(litemallGoodsProperty.getIsDefault()));
					vos.add(v);
				}
				propertyVo.setVos(vos);
				propertyVos.add(propertyVo);
			}
		}
		vo.setPropertyVos(propertyVos);

		//查看选择配方
		LumiereGoodsFormulaCorrelation goodsFormulaCorrelation = lumiereGoodsFormulaCorrelationService.getOne(Wrappers.lambdaQuery(LumiereGoodsFormulaCorrelation.class)
				.eq(LumiereGoodsFormulaCorrelation::getGoodsId, goods.getId()));
		//vo.setIsFormula(goodsFormulaCorrelation != null);

		if(goodsFormulaCorrelation == null){
			return ResponseUtil.ok(vo);
		}
		//配方
		LumiereFormula formula = lumiereFormulaService.getById(goodsFormulaCorrelation.getFormulaId());
		vo.setFormula(formula);
		LumiereFormulaType formulaType = lumiereFormulaTypeService.getById(formula.getFormulaTypeId());
		vo.setFormulaType(formulaType.getType());

		//配方详情
		List<PackageCategoryGoodsVO.GoodsFormulaVO> goodsFormulas = new ArrayList<>();
		//配方规格
		List<LumiereFormulaSpecifications> formulaSpecifications = lumiereFormulaSpecificationsService.list(Wrappers.lambdaQuery(LumiereFormulaSpecifications.class).eq(LumiereFormulaSpecifications::getFormulaId, goodsFormulaCorrelation.getFormulaId()));

		for (LumiereFormulaSpecifications formulaSpecification : formulaSpecifications) {
			//配方  规格[配方原料+配方规格数据配比]
			PackageCategoryGoodsVO.GoodsFormulaVO goodsFormula =  new PackageCategoryGoodsVO.GoodsFormulaVO();

			//配方规格数据配比
			List<LumiereFormulaSpecificationsDataProportioning> formulaSpecificationsDataProportionings = lumiereFormulaSpecificationsDataProportioningService.selectJoinList(LumiereFormulaSpecificationsDataProportioning.class,new MPJLambdaWrapper<LumiereFormulaSpecificationsDataProportioning>()
					.selectAll(LumiereFormulaSpecificationsDataProportioning.class)
					.leftJoin(LumiereFormulaMaterial.class,LumiereFormulaMaterial::getId,LumiereFormulaSpecificationsDataProportioning::getFormulaMaterialId)
					.eq(LumiereFormulaSpecificationsDataProportioning::getFormulaSpecificationsId, formulaSpecification.getId())
					.eq(LumiereFormulaSpecificationsDataProportioning::getIsDisplay,1)
					.orderByDesc(LumiereFormulaSpecificationsDataProportioning::getGroupName)
			);

			//配方规格数据配比 转换成 配方原料+配方规格数据配比 ，此刻配方原料数据为空
			List<PackageFormulaSpecificationsDataProportioningAndMaterialVO> formulaSpecificationsDataProportioningAndMaterialVOList = CollStreamUtil.toList(formulaSpecificationsDataProportionings,formulaSpecificationsDataProportioning->{
				PackageFormulaSpecificationsDataProportioningAndMaterialVO formulaSpecificationsDataProportioningAndMaterial = new PackageFormulaSpecificationsDataProportioningAndMaterialVO();
				BeanUtils.copyProperties(formulaSpecificationsDataProportioning,formulaSpecificationsDataProportioningAndMaterial);
				return formulaSpecificationsDataProportioningAndMaterial;
			});
			//配方原料+配方规格数据配比 ，填充配方原料数据为空
			formulaSpecificationsDataProportioningAndMaterialVOList.forEach(formulaSpecificationsDataProportioningAndMaterialVO->{
				LumiereFormulaMaterial lumiereFormulaMaterial = lumiereFormulaMaterialService.getById(formulaSpecificationsDataProportioningAndMaterialVO.getFormulaMaterialId());
				formulaSpecificationsDataProportioningAndMaterialVO.setMaterialName(lumiereFormulaMaterial.getMaterialName());
				formulaSpecificationsDataProportioningAndMaterialVO.setMaterialImg(lumiereFormulaMaterial.getMaterialImg());

				formulaSpecificationsDataProportioningAndMaterialVO.setMaterialClassificationName(lumiereFormulaMaterial.getMaterialClassificationName());
			});


			//配方规格+[配方原料+配方规格数据配比]
			goodsFormula.setFormulaSpecifications(formulaSpecification);

			//分主料
			List<PackageFormulaSpecificationsDataProportioningAndMaterialVO> filterMaterialTypeMaster = formulaSpecificationsDataProportioningAndMaterialVOList.stream().filter(item -> item.getMaterialType() == 0).collect(Collectors.toList());
			Map<Integer, List<PackageFormulaSpecificationsDataProportioningAndMaterialVO>> integerListMapMaster = CollStreamUtil.groupByKey(filterMaterialTypeMaster, PackageFormulaSpecificationsDataProportioningAndMaterialVO::getGroupName);
			goodsFormula.setFormulaSpecificationsDataProportioningsMaster(integerListMapMaster.values());

			//分辅料
			List<PackageFormulaSpecificationsDataProportioningAndMaterialVO> filterMaterialTypeSlave = formulaSpecificationsDataProportioningAndMaterialVOList.stream().filter(item->item.getMaterialType()==1).collect(Collectors.toList());
			Map<Integer, List<PackageFormulaSpecificationsDataProportioningAndMaterialVO>> integerListMapSlave = CollStreamUtil.groupByKey(filterMaterialTypeSlave, PackageFormulaSpecificationsDataProportioningAndMaterialVO::getGroupName);
			goodsFormula.setFormulaSpecificationsDataProportioningsSlave(integerListMapSlave.values());
			goodsFormulas.add(goodsFormula);
		}
		vo.setGoodsFormulas(goodsFormulas);

		//商品税费
		LitemallGoodsRegion goodRegion = litemallGoodsRegionService.findByGidAndCityId(goods.getId(), getShopCityRegionId(shopId));
		if (null == goodRegion) {
			//throw new BusinessRuntimeException(ORDER_GOODS_SHOP_INVALID_OPERATION, "该店铺无操作商品的权限");
		}
		vo.setGoodsTaxs(CollUtil.newArrayList());
		if(0<goodRegion.getTaxTypes().length){
			List<GoodsDetaiTaxVo> goodsTaxs = litemallTaxService.selectEnabledByIds(Arrays.asList(goodRegion.getTaxTypes())).stream().map(litemallTax -> {
						if (null == litemallTax) {
							//throw new BusinessRuntimeException(TAX_REGION_NOT_SET, "该区域未配置税收类型");
						} else if (litemallTax.getDeleted() || (!litemallTax.getEnable())) {
							return null;
						}
						return new GoodsDetaiTaxVo().setCode(litemallTax.getCode()).setValue(litemallTax.getValue());
					})
					.filter(Objects::nonNull)
					.collect(Collectors.toList());
			vo.setGoodsTaxs(goodsTaxs);
		}
		return ResponseUtil.ok(vo);
    }

    /**
     * 根据条件搜素跟店铺同一地区的总部商品和店铺商品）
     * @return
     */
    public List<LitemallGoods> list(Integer shopId, Integer catId, Integer brandId, String keywords, Boolean isHot, Boolean isNew, Integer page, Integer limit, String sort, String order) {
    	//查询列表数据
		GoodsQueryVo query = new GoodsQueryVo();
		query.setShopId(shopId);
		query.setCatId(catId);
		query.setBrandId(brandId);
		query.setIsHot(isHot);
		query.setIsNew(isNew);
		query.setIsOnSale(true);
		query.setKeywordsOrName(keywords);

		//查询店铺的区域地址
		Integer countryRegionId = null;
		Integer provinceRegionId = null;
		Integer cityRegionId = null;
		List<LitemallShopRegion> litemallShopRegions = shopRegionService.queryByShopId(shopId);
		if(!CollectionUtils.isEmpty(litemallShopRegions)) {
			for (LitemallShopRegion litemallShopRegion : litemallShopRegions) {
				LitemallRegion litemallRegion = litemallRegionService.findById(litemallShopRegion.getRegionId());
				if(Constants.REGION_TYPE_COUNTRY == litemallRegion.getType()) {
					countryRegionId = litemallShopRegion.getRegionId();
				}else if(Constants.REGION_TYPE_PROVINCE == litemallRegion.getType()) {
					provinceRegionId = litemallShopRegion.getRegionId();
				}else if(Constants.REGION_TYPE_CITY == litemallRegion.getType()){
					cityRegionId = litemallShopRegion.getRegionId();
				}
			}
		}
		query.setCountryRegionId(countryRegionId);
		query.setProvinceRegionId(provinceRegionId);
		query.setCityRegionId(cityRegionId);

		return goodsService.queryShopGoodsByCondition(query, page, limit, sort, order);
    }

    public List<WxCategoryVo> getCateL1(){
		List<LitemallCategory> categories = categoryService.queryL1();
		return Convert.convert(new TypeReference<List<WxCategoryVo>>() {}, categories);
	}

	public List<WxCategoryVo> getCateL2(Integer id){
		List<LitemallCategory> categories = categoryService.queryByPid(id);
		return  Convert.convert(new TypeReference<List<WxCategoryVo>>() {}, categories);
	}

	public Response getCateL3(Integer categoryId,Integer shopId){
		List<CategoryListVO> categoryList = new ArrayList<>();
		LitemallCategory categoryL2 = categoryService.findById(categoryId);
		//if(categoryL2 == null || !categoryL2.getLevel().equals(Constants.CATEGORY_LEVEL_L2)){return ResponseUtil.fail(CATEGORY_L2_ID_ERROR,"二级类目id错误");}

		//店铺商品列表（查询跟店铺同一地区的总部商品和店铺商品）
		List<Integer> goodsIds = CollStreamUtil.toList(getShopGoodsIds(shopId), goodsRegion->goodsRegion.getGoodsId());

		//店铺套餐列表
		List<Integer> packageIds = CollStreamUtil.toList(getShopGoodsIds(shopId), goodsRegion->goodsRegion.getPackageId());

		//[{name:'类目',list:['商品|套餐']}] {purl:,name:'',isPackage:true}

		List<LitemallCategory> categoriesL3 = categoryService.queryByPid(categoryL2.getId());
		if(goodsIds.size()==0&&packageIds.size()==0){
			categoriesL3.forEach(item->categoryList.add(new CategoryListVO(item.getName(),CollUtil.newArrayList())));
			return ResponseUtil.ok(categoryList);
		}

		if(goodsIds.size()>0){
			//过滤不属于当前门店的商品
			List<LitemallGoods> filterGoodsList = goodsService.findByIds(goodsIds);
			//此方法直接修改原集合
			CollUtil.filter(filterGoodsList, (Filter<LitemallGoods>) goods ->  (goods.getShopId() == null || goods.getShopId() == shopId.intValue()) && goods.getIsOnSale());

			//三级菜单分组
			for (LitemallCategory category : categoriesL3) {
				List<LitemallGoods> goodsList = filterGoodsList.stream().filter(goods -> goods.getCategoryId().intValue() == category.getId()).collect(Collectors.toList());
				if(goodsList.size()==0)continue;
				List<CategoryListVO.CategoryObjListVO> categoryGoodsList = CollStreamUtil.toList(goodsList, convertedGoods -> new CategoryListVO.CategoryObjListVO(convertedGoods.getId(), convertedGoods.getName(), convertedGoods.getPicUrl(), false,getRetailPrice(convertedGoods.getId()).setScale(2),convertedGoods.getBrief(),convertedGoods.getIsNew(),convertedGoods.getIsHot()));
				categoryList.add(new CategoryListVO(category.getName(), categoryGoodsList));
			}
		}


		if(packageIds.size()>0){
			//过滤不属于当前门店的商品
			List<LumierePackage> filterPackageList = lumierePackageService.listByIds(packageIds);
			//此方法直接修改原集合
			CollUtil.filter(filterPackageList, (Filter<LumierePackage>) packageGoods ->  (packageGoods.getShopId() == null || packageGoods.getShopId() == shopId.intValue()) && packageGoods.getIsOnSale());

			//三级菜单分组
			for (LitemallCategory category : categoriesL3) {
				List<LumierePackage> packageList = filterPackageList.stream().filter(packageGoods -> packageGoods.getCategoryId().intValue() == category.getId()).collect(Collectors.toList());
				if(packageList.size()==0)continue;
				List<CategoryListVO.CategoryObjListVO> categoryPackageList = CollStreamUtil.toList(packageList,convertedPackage->new CategoryListVO.CategoryObjListVO(convertedPackage.getId(), convertedPackage.getPackageName(), convertedPackage.getPackageImg(), true,convertedPackage.getAmount(),convertedPackage.getPackageIntroduction(),convertedPackage.getIsNew(),convertedPackage.getIsHot()));
				categoryList.add(new CategoryListVO(category.getName(),categoryPackageList));
			}
		}
		return ResponseUtil.ok(categoryList);
		/*List<LitemallCategory> categories = categoryService.queryByPid(id);
		List<WxCategoryVo> vos = categories.stream().map(cate -> {
			WxCategoryVo vo = new WxCategoryVo();
			BeanUtils.copyProperties(cate,vo);

			//根据三级分类Id查询商品
			List<LitemallGoods> goodsList = goodsService.findByCategoryIdAndShopId(cate.getId(),shopId);

			goodsList = goodsList.stream().filter(goods -> {
				List<LitemallGoodsRegion> goodsRegions = goodsRegionService.queryByGid(goods.getId());
				List<Integer> cityIds = goodsRegions.stream().map(LitemallGoodsRegion::getCityId).collect(Collectors.toList());
				List<LitemallShopRegion> shopRegions = shopRegionService.queryByShopIdAndRegionIds(shopId, cityIds);

				if (shopRegions != null && shopRegions.size() > 0) {
					return true;
				} else {
					return false;
				}
			}).collect(Collectors.toList());

			List<GoodsVo> goodsVos = goodsList.stream().map(gs -> {
				GoodsVo gvo = new GoodsVo();
				BeanUtils.copyProperties(gs,gvo);
				gvo.setPicUrl(gs.getPicUrl());
				gvo.setRetailPrice(getRetailPrice(gs.getId()).setScale(2));
				return gvo;
			}).collect(Collectors.toList());
			vo.setGoodsVos(goodsVos);

			return  vo;
		}).collect(Collectors.toList());
		return vos;*/
	}

	//获取门店商品Id集合
	public List<LitemallGoodsRegion> getShopGoodsIds(Integer shopId){
		if(shopId==null)return CollUtil.newArrayList();
		List<LitemallShopRegion> shopRegions = shopRegionService.queryByShopId(shopId);
		LitemallShopRegion shopRegionCity = shopRegions.get(shopRegions.size() - 1);
		return goodsRegionService.list(Wrappers.lambdaQuery(LitemallGoodsRegion.class).eq(LitemallGoodsRegion::getCityId, shopRegionCity.getRegionId()));
	}

	private BigDecimal getRetailPrice(Integer goodsId) {
		LumiereGoodsFormulaCorrelation goodsFormulaCorrelation = lumiereGoodsFormulaCorrelationService.getGoodsFormulaByGoodsId(goodsId);
		if (goodsFormulaCorrelation==null) {return BigDecimal.ZERO;}
		List<LumiereFormulaSpecifications> formulaSpecifications = lumiereFormulaSpecificationsService.selectListByFormulaId(goodsFormulaCorrelation.getFormulaId());
		if (CollUtil.isEmpty(formulaSpecifications)) {return BigDecimal.ZERO;}
		LumiereFormulaSpecifications defaultFormulaSpecifications = CollUtil.findOne(formulaSpecifications, item -> item.getIsDefault());
		return defaultFormulaSpecifications!=null?defaultFormulaSpecifications.getSpecificationsPrice():formulaSpecifications.get(0).getSpecificationsPrice();
	}

	/**
	 * 编辑详细信息
	 *
	 * @return {@link Response}
	 */
	public Response editDetail(Integer cartId) {
		//得到购物车详情
		LitemallCart cart = litemallCartService.findById(cartId);
		//得到购物车商品详情
		LitemallGoods goods = goodsService.findById(cart.getGoodsId());

		GoodsDetailResponse response = new GoodsDetailResponse();
		GoodsDetailInfoVo info = new GoodsDetailInfoVo();
		BeanUtils.copyProperties(goods, info);
		response.setInfo(info);

		//查询规格列表
		List<GoodsDetailSpecVo> specifications = new ArrayList<>();
		List<LitemallGoodsSpecification> specList = specService.queryByGid(cart.getGoodsId());
		if(!CollectionUtils.isEmpty(specList)) {
			for (LitemallGoodsSpecification litemallGoodsSpecification : specList) {
				GoodsDetailSpecVo goodsDetailSpecVo = new GoodsDetailSpecVo();
				BeanUtils.copyProperties(litemallGoodsSpecification, goodsDetailSpecVo);

				//查询规格原料
				Integer specId = litemallGoodsSpecification.getId();
				List<LitemallGoodsSpecificationMerchandise> specMerList = specMerchandiseService.queryBySpecid(specId);
				List<GoodsDetailSpecMerVo> specMers = new ArrayList<>();
				for (LitemallGoodsSpecificationMerchandise litemallGoodsSpecificationMerchandise : specMerList) {
					GoodsDetailSpecMerVo goodsDetailSpecMerVo = new GoodsDetailSpecMerVo();
					BeanUtils.copyProperties(litemallGoodsSpecificationMerchandise, goodsDetailSpecMerVo);
					specMers.add(goodsDetailSpecMerVo);
				}
				goodsDetailSpecVo.setSpecMers(specMers);
				goodsDetailSpecVo.setPrice(goodsDetailSpecVo.getPrice().setScale(2));
				specifications.add(goodsDetailSpecVo);
			}

			info.setRetailPrice(specList.get(0).getPrice());
		}
		response.setSpecifications(specifications);

		//查询属性列表
		List<GoodsDetailPropVo> props = new ArrayList<>();
		List<LitemallGoodsProperty> propList = goodsPropertyService.queryByGoodsId(cart.getGoodsId());
		if(!CollectionUtils.isEmpty(propList)) {
			for (LitemallGoodsProperty litemallGoodsProperty : propList) {
				GoodsDetailPropVo goodsDetailPropVo = new GoodsDetailPropVo();
				BeanUtils.copyProperties(litemallGoodsProperty, goodsDetailPropVo);
				props.add(goodsDetailPropVo);
			}
		}
		response.setProps(props);

		//查询原料列表
		List<GoodsDetailAccessoryVo> accessorys = new ArrayList<>();
		List<LitemallGoodsAccessory> goodsAccessoryList = accessoryService.queryByGoodsId(cart.getGoodsId());
		if(!CollectionUtils.isEmpty(specList)) {
			for (LitemallGoodsAccessory litemallGoodsAccessory : goodsAccessoryList) {
				GoodsDetailAccessoryVo goodsDetailAccessoryVo = new GoodsDetailAccessoryVo();
				BeanUtils.copyProperties(litemallGoodsAccessory, goodsDetailAccessoryVo);
				goodsDetailAccessoryVo.setPrice(goodsDetailAccessoryVo.getPrice().setScale(2));
				accessorys.add(goodsDetailAccessoryVo);
			}
		}

		response.setAccessorys(accessorys);

		//属性
		List<GoodsDetailAttributeVo> attribute = new ArrayList<>();
		List<LitemallGoodsAttribute> attributeList = goodsAttributeService.queryByGid(cart.getGoodsId());
		if(!CollectionUtils.isEmpty(attributeList)) {
			for (LitemallGoodsAttribute litemallGoodsAttribute : attributeList) {
				GoodsDetailAttributeVo goodsDetailAttributeVo = new GoodsDetailAttributeVo();
				BeanUtils.copyProperties(litemallGoodsAttribute, goodsDetailAttributeVo);
				attribute.add(goodsDetailAttributeVo);
			}
		}
		response.setAttribute(attribute);

		//税收配置
		List<GoodsDetaiTaxVo> taxes = new ArrayList<>();
		Integer cityRegionId = getShopCityRegionId(cart.getShopId());
		LitemallGoodsRegion goodRegion = litemallGoodsRegionService.findByGidAndCityId(cart.getGoodsId(), cityRegionId);
		if(goodRegion != null) {
			Integer[] taxTypes = goodRegion.getTaxTypes();
			if(taxTypes.length > 0) {
				List<LitemallTax> taxList = litemallTaxService.selectEnabledByIds(CollectionUtils.arrayToList(taxTypes));
				if(!CollectionUtils.isEmpty(taxList)) {
					for (LitemallTax litemallTax : taxList) {
						GoodsDetaiTaxVo goodsDetaiTaxVo = new GoodsDetaiTaxVo();
						BeanUtils.copyProperties(litemallTax, goodsDetaiTaxVo);
						taxes.add(goodsDetaiTaxVo);
					}
				}
			}
		}
		response.setTaxes(taxes);
		// 根据用户购物车设置默认选项
		if (cart.getUserId() != null) {
			Integer[] specificationIds = cart.getSpecificationIds();
			if(specificationIds != null){
				//设置默认选择规格
				if(specifications != null){
					for(GoodsDetailSpecVo goodsDetailSpecVo : specifications){
						boolean anyMatch = Arrays.stream(specificationIds).anyMatch(i ->
							 i.equals(goodsDetailSpecVo.getId())
						);
						if(anyMatch){
							goodsDetailSpecVo.setSelected(true);
						}
					}
				}
				//TODO 设置默认选择属性
				if(props != null){
					for(GoodsDetailPropVo detailPropVo : props){
						List<LitemallCartGoodsProperty> litemallCartGoodsProperties = litemallCartGoodsPropertyService.queryByCartId(cart.getId());
						litemallCartGoodsProperties.forEach(cartGoodsProperties->{
							if(Arrays.asList(detailPropVo.getValues()).indexOf(cartGoodsProperties.getValue())> -1){
								detailPropVo.setSelectedValue(String.valueOf(cartGoodsProperties.getValue()));
							}
						});

					}
				}
				List<LitemallCartGoodsAccessory> litemallCartGoodsAccessorys = new ArrayList<>();
				//TODO 设置默认选择辅料
				List<LitemallCartGoodsAccessory> litemallCartGoodsAccessoryList = litemallCartGoodsAccessoryService.queryByCartId(cart.getId());
				litemallCartGoodsAccessorys.addAll(litemallCartGoodsAccessoryList);
				accessorys.stream().forEach(accessory -> {
					LitemallMerchandise mer = litemallMerchandiseService.findById(accessory.getMerchandiseId());
					if (mer != null) {

						if(litemallCartGoodsAccessorys.size() > 0){
							LitemallCartGoodsAccessory findObj = litemallCartGoodsAccessorys.stream().filter(item ->
								 item.getAccessoryId().equals(accessory.getId())
							).findFirst().orElse(null);
							if(findObj != null){
								accessory.setSelectNumber(findObj.getNumber());
							}
						}
					}
				});

			}
		}
		//已收藏
		LitemallCollect collect = collectService.queryByGoodsId(cart.getUserId(), cart.getGoodsId());
		response.setUserHasCollect(collect!=null?1:0);
		//设置选购数量
		response.setNumber(cart.getNumber());
		return ResponseUtil.ok(response);
	}

	public Response packageList(Integer shopId) {
		//获取所有指定门店 套餐
		List<LumierePackage> packageAll = lumierePackageService.list();

		//门店匹配的 套餐
		List<LitemallShopRegion> shopRegions = shopRegionService.queryByShopId(shopId);
		List<LitemallRegion> regions = litemallRegionService.findByIds(shopRegions.stream().map(shopRegion -> shopRegion.getRegionId()).collect(Collectors.toList()));
		//门店市区
		LitemallRegion regionCity = CollUtil.findOne(regions, region -> region.getType() == Constants.REGION_TYPE_CITY);

		//门店市区 匹配 所有套餐
		List<LumierePackage> packageList =  packageAll.stream()
				.filter(lumierePackage -> {
					LitemallGoodsRegion byPackageIdAndCityId = goodsRegionService.findByPackageIdAndCityId(lumierePackage.getId(), regionCity.getId());
					return lumierePackage.getShopId() == shopId || byPackageIdAndCityId != null;
				})
				.collect(Collectors.toList());
		return ResponseUtil.ok(packageList);
	}

	public Response packageDetailInfo(Integer shopId, Integer id) {
		PackageDetailRespVO packageDetail = new PackageDetailRespVO();
		//套餐
		LumierePackage lumierePackage = validationPackage(id);
		packageDetail.setLumierePackage(lumierePackage);

		List<PackageCategoryVO> packageCategory = new ArrayList<>();

		//类目
		List<LumierePackageCategory> categoryList = lumierePackageCategoryService.list(Wrappers.lambdaQuery(LumierePackageCategory.class).eq(LumierePackageCategory::getPackageId, id));
		//所有类目商品
		List<LumierePackageCategoryGoods> categoryGoodAll = lumierePackageCategoryGoodsService.list(Wrappers.lambdaQuery(LumierePackageCategoryGoods.class).eq(LumierePackageCategoryGoods::getPackageId, id));
		for (LumierePackageCategory lumierePackageCategory : categoryList) {
			List<LumierePackageCategoryGoods> categoryGoods = categoryGoodAll.stream().filter(packageCategoryGoods -> packageCategoryGoods.getPackageCategoryId() == lumierePackageCategory.getId()).collect(Collectors.toList());

			//类目 类目信息+类目下所有商品
			List<PackageCategoryGoodsVO> categoryGoodsVO = new ArrayList<>();

			for (LumierePackageCategoryGoods categoryGood : categoryGoods) {
				//商品详情
				PackageCategoryGoodsVO packageCategoryGoods = new PackageCategoryGoodsVO();

				//套餐类目下商品 配置信息
				packageCategoryGoods.setCategoryGoods(categoryGood);

				//商品信息
				LitemallGoods goods = goodsService.findById(categoryGood.getGoodsId());
				packageCategoryGoods.setGoods(goods);

				//查询属性列表
				List<GoodsPropertyVO> propertyVos = goodsPropertyService.queryByGoodsId(goods.getId()).stream()
						.map(litemallGoodsProperty -> {
							GoodsPropertyVO propertyVo = new GoodsPropertyVO();
							propertyVo.setId(litemallGoodsProperty.getId());
							propertyVo.setName(litemallGoodsProperty.getName());

							// 将字符串数组转换为 List<GoodsDetailPropertyVO>
							List<GoodsPropertyVO.GoodsDetailPropertyVO> vos = Arrays.stream(litemallGoodsProperty.getValues())
									.map(value -> {
										GoodsPropertyVO.GoodsDetailPropertyVO v = new GoodsPropertyVO.GoodsDetailPropertyVO();
										v.setName(value);
										v.setIsSelected(value.equals(litemallGoodsProperty.getIsDefault()));  // 选择第一个值
										return v;
									})
									.collect(Collectors.toList());

							propertyVo.setVos(vos);
							return propertyVo;
						})
						.collect(Collectors.toList());

				packageCategoryGoods.setGoodsProperties(propertyVos);

				//一个人

				//查看选择配方
				LumiereGoodsFormulaCorrelation goodsFormulaCorrelation = lumiereGoodsFormulaCorrelationService.getOne(Wrappers.lambdaQuery(LumiereGoodsFormulaCorrelation.class)
						.eq(LumiereGoodsFormulaCorrelation::getGoodsId, categoryGood.getGoodsId()));

				//配方详情
				List<PackageCategoryGoodsVO.GoodsFormulaVO> goodsFormulas = new ArrayList<>();
				//配方规格
				List<LumiereFormulaSpecifications> formulaSpecifications = lumiereFormulaSpecificationsService.list(Wrappers.lambdaQuery(LumiereFormulaSpecifications.class).eq(LumiereFormulaSpecifications::getFormulaId, goodsFormulaCorrelation.getFormulaId()));
				//packageCategoryGoods.setFormulaSpecifications(formulaSpecifications);
				//packageCategoryGoods.setGoodsSpecification(CollUtil.newArrayList());

				for (LumiereFormulaSpecifications formulaSpecification : formulaSpecifications) {
					//配方  规格[配方原料+配方规格数据配比]
					PackageCategoryGoodsVO.GoodsFormulaVO goodsFormula =  new PackageCategoryGoodsVO.GoodsFormulaVO();

					//配方规格数据配比
					/*List<LumiereFormulaSpecificationsDataProportioning> formulaSpecificationsDataProportionings = lumiereFormulaSpecificationsDataProportioningService.list(Wrappers.lambdaQuery(LumiereFormulaSpecificationsDataProportioning.class)
							.eq(LumiereFormulaSpecificationsDataProportioning::getFormulaSpecificationsId, formulaSpecification.getId()));*/

					List<LumiereFormulaSpecificationsDataProportioning> formulaSpecificationsDataProportionings = lumiereFormulaSpecificationsDataProportioningService.selectJoinList(LumiereFormulaSpecificationsDataProportioning.class,new MPJLambdaWrapper<LumiereFormulaSpecificationsDataProportioning>()
							.selectAll(LumiereFormulaSpecificationsDataProportioning.class)
							.leftJoin(LumiereFormulaMaterial.class,LumiereFormulaMaterial::getId,LumiereFormulaSpecificationsDataProportioning::getFormulaMaterialId)
							.eq(LumiereFormulaSpecificationsDataProportioning::getFormulaSpecificationsId, formulaSpecification.getId())
							.eq(LumiereFormulaSpecificationsDataProportioning::getIsDisplay,1)
							.orderByDesc(LumiereFormulaSpecificationsDataProportioning::getGroupName)
					);


					//配方规格数据配比 转换成 配方原料+配方规格数据配比 ，此刻配方原料数据为空
					List<PackageFormulaSpecificationsDataProportioningAndMaterialVO> formulaSpecificationsDataProportioningAndMaterialVOList = formulaSpecificationsDataProportionings.stream()
							.map(formulaSpecificationsDataProportioning->{
								return BeanUtil.toBean(formulaSpecificationsDataProportioning,PackageFormulaSpecificationsDataProportioningAndMaterialVO.class);
							})
							.collect(Collectors.toList());
					//配方原料+配方规格数据配比 ，填充配方原料数据为空
					formulaSpecificationsDataProportioningAndMaterialVOList.forEach(formulaSpecificationsDataProportioningAndMaterialVO->{
						LumiereFormulaMaterial lumiereFormulaMaterial = lumiereFormulaMaterialService.getById(formulaSpecificationsDataProportioningAndMaterialVO.getFormulaMaterialId());
						formulaSpecificationsDataProportioningAndMaterialVO.setMaterialName(lumiereFormulaMaterial.getMaterialName());
						formulaSpecificationsDataProportioningAndMaterialVO.setMaterialImg(lumiereFormulaMaterial.getMaterialImg());
						formulaSpecificationsDataProportioningAndMaterialVO.setMaterialClassificationName(lumiereFormulaMaterial.getMaterialClassificationName());
					});

					//配方规格+[配方原料+配方规格数据配比]
					goodsFormula.setFormulaSpecifications(formulaSpecification);

					//分主料
					List<PackageFormulaSpecificationsDataProportioningAndMaterialVO> filterMaterialTypeMaster = formulaSpecificationsDataProportioningAndMaterialVOList.stream().filter(item -> item.getMaterialType() == 0).collect(Collectors.toList());
					Map<Integer, List<PackageFormulaSpecificationsDataProportioningAndMaterialVO>> integerListMapMaster = CollStreamUtil.groupByKey(filterMaterialTypeMaster, PackageFormulaSpecificationsDataProportioningAndMaterialVO::getGroupName);
					goodsFormula.setFormulaSpecificationsDataProportioningsMaster(integerListMapMaster.values());

					//分辅料
					List<PackageFormulaSpecificationsDataProportioningAndMaterialVO> filterMaterialTypeSlave = formulaSpecificationsDataProportioningAndMaterialVOList.stream().filter(item->item.getMaterialType()==1).collect(Collectors.toList());
					Map<Integer, List<PackageFormulaSpecificationsDataProportioningAndMaterialVO>> integerListMapSlave = CollStreamUtil.groupByKey(filterMaterialTypeSlave, PackageFormulaSpecificationsDataProportioningAndMaterialVO::getGroupName);
					goodsFormula.setFormulaSpecificationsDataProportioningsSlave(integerListMapSlave.values());

					//配方规格+[配方原料+配方规格数据配比]
					goodsFormula.setFormulaSpecifications(formulaSpecification);

					goodsFormulas.add(goodsFormula);
				}
				packageCategoryGoods.setGoodsFormulas(goodsFormulas);
				categoryGoodsVO.add(packageCategoryGoods);
			}
			packageCategory.add(new PackageCategoryVO(lumierePackageCategory,categoryGoodsVO));
		}
		//税收配置
		LitemallGoodsRegion goodRegion = litemallGoodsRegionService.findByPackageIdAndCityId(id, getShopCityRegionId(shopId));
		List<LitemallTax> taxList = goodRegion == null || goodRegion.getTaxTypes().length == 0 ?
				CollUtil.newArrayList() : litemallTaxService.selectEnabledByIds(CollectionUtils.arrayToList(goodRegion.getTaxTypes()));
		packageDetail.setTaxList(taxList);

		packageDetail.setPackageCategorys(packageCategory);
		return ResponseUtil.ok(packageDetail);
	}

	@VisibleForTesting
	private LumierePackage validationPackage(Integer packageId){
		//套餐
		LumierePackage lumierePackage = lumierePackageService.getById(packageId);
		if(lumierePackage==null){
			throw exception(LUMIERE_PACKAGE_IS_NULL);
		}
		//lumierePackage.setAmount(lumierePackage.getAmount().setScale(2, RoundingMode.HALF_UP));
		return lumierePackage;
	}



}
